package math

import (
	"JVM/Jvmgo/GoToJVM/instructions/base"
	"JVM/Jvmgo/GoToJVM/runtimeData"
)

/*
	位移指令，分为：
			1. 有符号
			2. 无符号
*/

type ISHL struct {
	base.NoOperandsInstruction
}
type LSHL struct {
	base.NoOperandsInstruction
}
type ISHR struct {
	base.NoOperandsInstruction
}
type LSHR struct {
	base.NoOperandsInstruction
}
type IUSHR struct {
	base.NoOperandsInstruction
}
type LUSHR struct {
	base.NoOperandsInstruction
}

func (self *ISHR) Execute(frame *runtimeData.Frame) {
	stack := frame.OperandStack()
	val2 := stack.PopInt() // 位移多少位
	val1 := stack.PopInt() // 被位移的数
	// int只有32位，低五位就足够表示位移数
	// 同时由于Go位移操作右侧必须为无符号整数所以进行类型转换
	s := uint32(val2) & 0x1f
	res := val1 << s
	stack.PushInt(res)
}
func (self *ISHL) Execute(frame *runtimeData.Frame) {
	stack := frame.OperandStack()
	val2 := stack.PopInt()
	val1 := stack.PopInt()
	s := uint32(val2) & 0x1f
	res := val1 >> s
	stack.PushInt(res)
}
func (self *LSHR) Execute(frame *runtimeData.Frame) {
	stack := frame.OperandStack()
	val2 := stack.PopInt()
	val1 := stack.PopLong()
	s := uint32(val2) & 0x3f
	res := val1 >> s
	stack.PushLong(res)
}
func (self *LSHL) Execute(frame *runtimeData.Frame) {
	stack := frame.OperandStack()
	val2 := stack.PopInt()
	val1 := stack.PopLong()
	s := uint32(val2) & 0x3f
	res := val1 << s
	stack.PushLong(res)
}
func (self IUSHR) Execute(frame *runtimeData.Frame) {
	stack := frame.OperandStack()
	val2 := stack.PopInt()
	val1 := stack.PopInt()
	s := uint32(val2) & 0x1f
	res := int32(uint32(val1) >> s)
	stack.PushInt(res)
}
func (self LUSHR) Execute(frame *runtimeData.Frame) {
	stack := frame.OperandStack()
	val2 := stack.PopInt()
	val1 := stack.PopLong()
	s := uint32(val2) & 0x3f
	res := int64(uint64(val1) >> s)
	stack.PushLong(res)
}
